#include "mbed.h"
 
//define Serial Bus Address
//to comunitate with the INA3221, the master must first address
//slave devices with a slave address byte.
//this byte consist of 7 address bits and a direction bit to indicate whether 
//the intend action is a read or write 
//第一步寻址，发送一个字节，其内容就是 7位地址+1位方向
// define address pins and slave addresses

#define INA_GND     (0x80) 
#define INA_VS      (0x82) 
#define INA_SDA     (0x80) //80 is first one // 82 is second one in tx2
#define INA_SCL     (0x87) 


#define Rs_channel_1 0.02
#define Rs_channel_2 0.01
#define Rs_channel_3 0.01

// init stm i2c 
I2C i2c(I2C_SDA, I2C_SCL);
// init led
DigitalOut myled(LED1);
//init mini usb
Serial pc(SERIAL_TX, SERIAL_RX);
 
volatile char TempCelsiusDisplay[] = "+abc.d V";

int translate(int reg)
{
    reg = reg -1;
    //printf("temp = %d\n",reg);
    int temp = ~reg;
    temp = temp >>3;
    temp = temp & 0xfff;
    //printf("temp = %d\n",temp);
    if(reg > 32759)//判断正负 因为最大值是7ff8 = 32760 所以超过即为负数
        temp = -temp;
    return temp;
}


int main()
{
 
    char data_write[10];
    char data_read[2];
		char channel_1_shunt_v[2];
		char channel_1_bus_v[2];
		char channel_2_shunt_v[2];
		char channel_2_bus_v[2];
		char channel_3_shunt_v[2];
		char channel_3_bus_v[2];
	
	  //char menu_id[2];//for test ina2331
    /* Configure the Temperature sensor device STLM75:
    - Thermostat mode Interrupt
    - Fault tolerance: 0
    */
    data_write[0] = 0x0;
    //data_write[1] = 0x00;
    int status = i2c.write(0x82, data_write, 1, 0);
    if (status != 0) { // Error
        while (1) {
            myled = !myled;
            wait(1);
						pc.printf("hello world!  ");
						//printf("this is test for printf\n");
        }
    }
 
    while (1) {
        // Read temperature register
			  //pc.printf("address test succeed  ");
						
				//menu ID
        data_write[0] = 0xfe;	
        i2c.write(INA_SDA, data_write, 1, 0); // no stop
        i2c.read(INA_SDA | 1, data_read, 2, 0);	
			
			  //chanel_1 shunt voltage
				data_write[0] = 0x01;
				i2c.write(INA_SDA,data_write , 1, 1); // no stop
			  i2c.read(INA_SDA | 1, channel_1_shunt_v, 2, 0);
				//chanel_1 bus voltage
			
				data_write[0] = 0x02;
			  i2c.write(INA_SDA,data_write , 1, 1); // no stop
			  i2c.read(INA_SDA | 1, channel_1_bus_v, 2, 0);
				//translate(channel_1_bus_v[1]);
					
			  //chanel_2 shunt voltage
				data_write[0] = 0x03;
				i2c.write(INA_SDA,data_write , 1, 1); // no stop
			  i2c.read(INA_SDA | 1, channel_2_shunt_v, 2, 0);
				//translate(channel_2_shunt_v[1]);
				
				//chanel_2 bus voltage
				data_write[0] = 0x04;
				i2c.write(INA_SDA,data_write , 1, 1); // no stop
			  i2c.read(INA_SDA | 1, channel_2_bus_v, 2, 0);
		
				
			  //chanel_3 shunt voltage
				data_write[0] = 0x05;
				i2c.write(INA_SDA,data_write , 1, 1); // no stop
			  i2c.read(INA_SDA | 1, channel_3_shunt_v, 2, 0);
				//translate(channel_3_shunt_v[1]);
				
				//chanel_3 bus voltage
				data_write[0] = 0x06;
			  i2c.write(INA_SDA,data_write , 1, 1); // no stop
			  i2c.read(INA_SDA | 1, channel_3_bus_v, 2, 0);
	  
			
			
        // translate the two char to one int num
        int menuID = (int)((int)data_read[0] << 8) | data_read[1];
				
				pc.printf("Manu ID = %x ", menuID);
				
				unsigned int channel_1_shuntV = (unsigned int)((int)channel_1_shunt_v[0] << 8) | channel_1_shunt_v[1];
				
				unsigned int channel_1_busV 	 = (unsigned int)((int)channel_1_bus_v[0] << 8)   | channel_1_bus_v[1];
				
				unsigned int channel_2_shuntV = (unsigned int)((int)channel_2_shunt_v[0] << 8) | channel_2_shunt_v[1];
				
				unsigned int channel_2_busV   = (unsigned int)((int)channel_2_bus_v[0] << 8)   | channel_2_bus_v[1];
				
				unsigned int channel_3_shuntV = (unsigned int)((int)channel_3_shunt_v[0] << 8) | channel_3_shunt_v[1];
				
				unsigned int channel_3_busV   = (unsigned int)((int)channel_3_bus_v[0] << 8)   | channel_3_bus_v[1];
				
				
				//pc.printf("channel_1_busV   = %d  ",channel_1_busV);
				//pc.printf("channel_2_busV   = %d  ",channel_2_shuntV);
				//pc.printf("channel_3_busV   = %d  ",channel_3_shuntV);
				
				
				//channel_1_shuntV = translate(channel_1_shuntV);
				//channel_1_busV   = translate(channel_1_busV);
				//channel_2_shuntV = translate(channel_2_shuntV);
				//channel_2_busV   = translate(channel_2_busV);
				//channel_3_shuntV = translate(channel_3_shuntV);
				//channel_3_busV   = translate(channel_3_busV);
				//calculate the voltage and power
	
				// busV = channel_x_busV/8*8 mV 
				// 解释 bus 即 供电电压，channel 值 为寄存器值， 
				// 除以8 表示 右移三位，因为其寄存器低三位不存数据，最高位为符号位 ，
				// 乘以8 表示 寄存器最低单位 1 = 8 mV
				// 因此从寄存器的电压值，可以直接用，无需再改动
				// ShuntV = reg/8 * 40 uV
				// shunt 表示一个感应电压
				// 除以8 还是表示移位
				// 乘以40uV 表示单位。。。转化成 mV 即 0.04,,V 0.00004
			/*	
				float c1_shuntV_0 = (float)channel_1_shuntV/8 * 0.00004;
				float c2_shuntV_0 = (float)channel_2_shuntV/8 * 0.00004;
				float c3_shuntV_0 = (float)channel_3_shuntV/8 * 0.00004;
				
				float c1_shuntV = (float)translate(channel_1_shuntV)*0.00004;
				float c2_shuntV = (float)translate(channel_2_shuntV)*0.00004;
				float c3_shuntV = (float)translate(channel_3_shuntV)*0.00004;
				
				// ture I = reg/8 * 40uV/Rs     notice ， Rs is the channel sampling Resistance
				// POWER  =  U*I
				// board == TX1
				
				
				float total_I = channel_1_shuntV/8*0.04/Rs_channel_1;
				float gpu_I 	= channel_2_shuntV/8*0.04/Rs_channel_2;
				float cpu_I 	= channel_2_shuntV/8*0.04/Rs_channel_3;
				*/				
				// 由 mV ==> V
				/*
				float total_V = (float)channel_1_busV/1000;
				float gpu_V   = (float)channel_2_busV/1000;
				float cpu_V   = (float)channel_3_busV/1000;
			
				float total_I = c1_shuntV/Rs_channel_1;
				float gpu_I 	= c2_shuntV/Rs_channel_2;
				float cpu_I 	= c3_shuntV/Rs_channel_3;
				
				float total_P = c1_shuntV * total_I;
				float gpu_P   = c2_shuntV * gpu_I;
				float cpu_P   = c3_shuntV * cpu_I;
			  	
		  	//int temp = (int)((int)data[0] << 8) | data[1];
			  //int menuId = (int)((int)menu_id[0] << 8) | menu_id[1];
        //tempval >>= 3;  //remove lower 3 bit
				*/
				
       	pc.printf("channel_1_busV   = %d  ",channel_1_busV);
				pc.printf("channel_2_busV   = %d  ",channel_2_busV);
				pc.printf("channel_3_busV   = %d  ",channel_3_busV);
				pc.printf("channel_1_shuntV   = %d  ",channel_1_shuntV);
				pc.printf("channel_2_shuntV   = %d  ",channel_2_shuntV);
				pc.printf("channel_3_shuntV   = %d  ",channel_3_shuntV);	
				
			  /*
				// Display result
				
       	pc.printf("channel_1_busV   = %f  ",total_V);
				pc.printf("channel_2_busV   = %f  ",gpu_V);
				pc.printf("channel_3_busV   = %f  ",cpu_V);
				
				pc.printf("channel_1_shuntV   = %f  ",c1_shuntV);
				pc.printf("channel_2_shuntV   = %f  ",c2_shuntV);
				pc.printf("channel_3_shuntV   = %f  ",c3_shuntV);	
				
				pc.printf("channel_1_shuntV_0   = %f  ",c1_shuntV_0);
				pc.printf("channel_2_shuntV_0   = %f  ",c2_shuntV_0);
				pc.printf("channel_3_shuntV_0   = %f  ",c3_shuntV_0);	
				
				pc.printf("total_I = %f ",total_I );
				pc.printf("gpu_I = %f ",gpu_I );
				pc.printf("cpu_I = %f ",cpu_I );
				
				pc.printf("total_P = %f ",total_P );
				pc.printf("gpu_P = %f ",gpu_P );
				pc.printf("cpu_P = %f ",cpu_P );
				
				*/	
        myled = !myled;
        wait(0.1);
    }
}
 
